##############################################################################################################################
# This is c-template project use cmake                                                                                       #
# author：1101627719@qq.com                                                                                                  #
# verision： v1.0.0                                                                                                          #
##############################################################################################################################

#============================================================================#
# Beautify output                                                            #
#                                                                            #
# If KBUILD_VERBOSE equals 0 then the above command will be hidden.          #
# If KBUILD_VERBOSE equals 1 then the above command is displayed.            #
#                                                                            #
# To put more focus on warnings, be less verbose as default                  #
# Use 'make V=1' to see the full commands                                    #
#============================================================================#
ifeq ("$(origin V)", "command line")
  KBUILD_VERBOSE = $(V)
endif
ifndef KBUILD_VERBOSE
  KBUILD_VERBOSE = 0
endif

ifeq ($(KBUILD_VERBOSE),1)
  quiet =
  Q =
else
  quiet=quiet_
  Q = @
endif

# Export these settings to child processes
export Q

#============================================================================#
# Build host system                                                          #
#============================================================================#
ifeq ($(findstring Linux, $(shell uname)), Linux) 
	BUILD_HOST = linux
else ifeq ($(findstring CYGWIN, $(shell uname)), CYGWIN)
	BUILD_HOST = cygwin
else
	BUILD_HOST = unkown
endif
# Export these settings to child processes
export BUILD_HOST

#============================================================================#
# Directory List                                                             #
#============================================================================#

# top dir
TOP_DIR := $(shell pwd)

# cmake dir
CMAKE_DIR := $(TOP_DIR)/cmake

# doc dir
DOC_DIR := $(TOP_DIR)/doc

# src dir
SRC_DIR := $(TOP_DIR)/core

# examples dir
EXAMPLES_DIR := $(TOP_DIR)/examples

# tools dir
TOOLS_DIR := $(TOP_DIR)/tools

#config dir
CONFIG_DIR := $(TOP_DIR)/config

# build dir
ifeq ($(BUILD_HOST), linux) 
BUILD_DIR := $(TOP_DIR)/build/linux
else ifeq ($(BUILD_HOST), cygwin)
BUILD_DIR := $(TOP_DIR)/build/cygwin
endif

# build_tools
ifeq ($(BUILD_HOST), linux) 
BUILD_TOOLS_DIR := $(TOP_DIR)/build_tools/linux
else ifeq ($(BUILD_HOST), cygwin)
BUILD_TOOLS_DIR := $(TOP_DIR)/build_tools/cygwin
endif

# Export these settings to child processes
export TOP_DIR CMAKE_DIR DOC_DIR SRC_DIR EXAMPLES_DIR TOOLS_DIR BUILD_DIR BUILD_TOOLS_DIR

#============================================================================#
# Target List                                                                #
#============================================================================#

######################################################################
# run test                                                           #
######################################################################    
.PHONY : test
test: debug
	@echo "Run test"
	$(BUILD_DIR)/bin/plum_ut.run


######################################################################
# check build host environment                                       #
###################################################################### 
.PHONY : check
check:
	@echo "Build host system: " $(BUILD_HOST)
ifeq ($(BUILD_HOST), unkown) 
	@exit 1
endif
	
######################################################################
# debug                                                              #
######################################################################
.PHONY : debug
debug:
	@echo "Build debug"
	$(Q) mkdir -p $(BUILD_DIR)/build_debug 2>/dev/null
	$(Q) cd $(BUILD_DIR)/build_debug && cmake -DCMAKE_TOOLCHAIN_FILE=$(CMAKE_DIR)/toolchain-public.cmake -DCMAKE_BUILD_TYPE=Release ../../.. && make -j8

######################################################################
# help                                                               #
######################################################################
.PHONY : help
help:
	$(Q) echo "=================================================================="
	$(Q) echo "Project layout, TOP: $(TOP_DIR)"
	$(Q) tree -d -L 1
	$(Q) echo "=================================================================="

	@echo "==Help targets=="
	@echo "help            - Show help menu"
	@echo ""
	@echo "==Cleaning targets=="
	@echo "clean           - Removing all obj files(build/*)"
	@echo ""
	@echo "==Code analysers and format=="
	@echo "lint            - Lint the project code (used scan-build), please first 'sudo apt install clang-tools'"
	@echo "codeformat      - Format the project code (used clang-format), please first 'sudo apt install clang-format'"
	@echo ""
	@echo "==Documentation targets=="
	@echo "documentation   - Build the documentation using doxygen, please first 'sudo apt install doxygen'"
	@echo ""
	@echo "==Configuration targets=="
	@echo "menuconfig      - Update current config utilising a menu based program"
	@echo "                  please first 'sudo apt install bison flex byacc gperf libncurses-dev (libncurses-devel)'"
	@echo ""
	@echo "==Build project targets=="
	@echo "debug           - Build for x64 debug ut"
	@echo "test            - Run for x64 debug ut"
	@echo "x64             - Build for x64"
	@echo "x86             - Build for x86"
	@echo "himix100        - Build for himix100"
	@echo "jz_t31          - Build for jz_t31"
	@echo "stm32           - Build for stm32"
	@echo "esp32           - Build for esp32"
	@echo "rasp            - Build for raspberrypi"

######################################################################
# Update current config utilising a menu based program               #
# - build_tools/kconfig-frontend                                     #
# - build_tools/kconfig-define                                       #
# _ build_tools/kconfig-cmake										 #
######################################################################
.PHONY : build_tools/kconfig-frontend
build_tools/kconfig-frontend:
	@echo "== build kconfig-frontend tools =="
	$(Q) mkdir -p $(BUILD_TOOLS_DIR)/kconfig-frontend && \
	cd $(BUILD_TOOLS_DIR)/kconfig-frontend && \
	cmake $(TOOLS_DIR)/kconfig/kconfig-frontend && make
	@echo "kconfig-frontend build result" $$?

.PHONY : build_tools/kconfig-define	
build_tools/kconfig-define:
	@echo "== build kconfig-define tools =="
	$(Q) mkdir -p $(BUILD_TOOLS_DIR)/kconfig-define && \
	cd $(BUILD_TOOLS_DIR)/kconfig-define && \
	cmake $(TOOLS_DIR)/kconfig/kconfig-define && make

.PHONY : build_tools/kconfig-cmake
build_tools/kconfig-cmake:
	@echo "== build kconfig-cmake tools =="
	$(Q) mkdir -p $(BUILD_TOOLS_DIR)/kconfig-cmake && \
	cd $(BUILD_TOOLS_DIR)/kconfig-cmake && \
	cmake $(TOOLS_DIR)/kconfig/kconfig-cmake && make
######################################################
# function:
# **kconfig_code_func(configfile, ouputfile), 
#   - cover ".config" to "xxx_config.h"
#   - configfile: ".config" abs path
#   - ouputfile: "xxxx_config.h"
######################################################

define kconfig_code_func
	@echo "conver kconfig to config code....."
	@echo "$(1) > $(2)"
	@echo ""
	@$(BUILD_TOOLS_DIR)/kconfig-define/kconfig-define $(1)
	@$(BUILD_TOOLS_DIR)/kconfig-define/kconfig-define $(1) > $(2)
endef

define cmake_code_func
	@echo "conver config file to cmake code..."
	@echo "$(1) > $(2)"
	@echo ""
	@$(BUILD_TOOLS_DIR)/kconfig-cmake/kconfig-cmake $(1)
	@$(BUILD_TOOLS_DIR)/kconfig-cmake/kconfig-cmake $(1) > $(2)
endef

define format_code_func
	@echo "git format ...."
	@echo "$(1) > $(2)"
	@echo ""
	if [ ! -f $(2) ];then 		\
		echo "the format file not exist!!";		\
		cat ${1} > ${2}	;		\
	fi;
endef

.PHONY : menuconfig
ROOT_KCONFIG = $(TOP_DIR)/Kconfig # root Kconfig file
AUTO_CONFIG_HFILE = $(SRC_DIR)/kernel/include/plum_config.h
CMAKE_CONFIG_HFILE = $(SRC_DIR)/../cmake/public_config.cmake
FORMAT_CONFIG_FILE = $(TOP_DIR)/.git/hooks/pre-commit
menuconfig: check build_tools/kconfig-frontend build_tools/kconfig-define build_tools/kconfig-cmake
	$(BUILD_TOOLS_DIR)/kconfig-frontend/kconfig-mconf $(ROOT_KCONFIG)
	$(call format_code_func,$(TOP_DIR)/tools/auto_format/pre-commit,$(FORMAT_CONFIG_FILE))
	$(call kconfig_code_func, $(TOP_DIR)/.config, $(AUTO_CONFIG_HFILE))
	$(call cmake_code_func, $(TOP_DIR)/.config, $(CMAKE_CONFIG_HFILE))
	
######################################################################
# Clean out the build directory                                      #
######################################################################
.PHONY : clean
clean:
	@echo "Removing all obj files(build/* and build_*_tools/*)"
	$(Q) rm -rf $(BUILD_DIR) $(BUILD_TOOLS_DIR)

######################################################################
# lint                                                               #
######################################################################
# analyze target enables use of clang's scan-build (if installed)    #
# will then need to run 'scan-build make' to compile and analyze     #
# 'scan-build -V make' will show the results graphically in your     #
# web browser                                                        #
# sudo apt install clang-tools                                       #
######################################################################
.PHONY : lint
lint:
	@echo "Lint the project code (used scan-build), please first 'sudo apt install clang-tools'"
	$(Q) mkdir -p $(BUILD_DIR)/build_lint 2>/dev/null
	$(Q) rm -rf $(BUILD_DIR)/build_lint/*
	$(Q) cd $(BUILD_DIR)/build_lint && scan-build cmake -DCMAKE_TOOLCHAIN_FILE=$(CMAKE_DIR)/toolchain-public.cmake ../../.. && scan-build -o analyze_result make -j8

######################################################################
# Format the project code                                            #
######################################################################
.PHONY : codeformat
codeformat:
	@echo "Format the project code (used clang-format), please first 'sudo apt install clang-format'"
	$(Q) cd $(TOOLS_DIR)/codeformat && ./codeformat.sh	
  	
######################################################################
# Build the documentation using doxygen                              #
######################################################################
.PHONY : documentation
documentation: $(BUILD_DIR)
	@echo "Build the documentation using doxygen, please first 'sudo apt install doxygen'"
	$(Q) cd $(DOC_DIR); \
	doxygen osal.doxyfile

.PHONY : gh-pages
gh-pages: documentation
	$(Q) cp -r $(BUILD_DIR)/documentation/html/* documentation/	
	
######################################################################
# Cross-compile using on *nix                                        #
# - x64                                                              #
# - x86                                                              #
# - stm32                                                            #
# - esp32                                                            #
######################################################################

############################
# x64                      #
############################
.PHONY : x64
x64:
	@echo "Build x64"
	$(Q) mkdir -p $(BUILD_DIR)/build_x64 2>/dev/null
	$(Q) rm -rf $(BUILD_DIR)/build_x64/*
	$(Q) cd $(BUILD_DIR)/build_x64;\
	cmake -DCMAKE_TOOLCHAIN_FILE=$(CMAKE_DIR)/x64.cmake -DCMAKE_BUILD_TYPE=Release ../../..;\
	make -j8

############################
# x86                      #
############################
.PHONY : x86
x86:
	@echo "Build x86"
	$(Q) mkdir -p $(BUILD_DIR)/build_x86 2>/dev/null
	$(Q) rm -rf $(BUILD_DIR)/build_x86/*
	$(Q) cd $(BUILD_DIR)/build_x86;\
	cmake -DCMAKE_TOOLCHAIN_FILE=$(CMAKE_DIR)/toolchain-public.cmake -DCMAKE_BUILD_TYPE=Release ../../..;\
	make -j8
	
############################
# himix100                 #
############################
.PHONY : himix100
himix100:
	@echo "Build himix100"
	$(Q) mkdir -p $(BUILD_DIR)/build_himix100 2>/dev/null
	$(Q) rm -rf $(BUILD_DIR)/build_himix100/*
	$(Q) cd $(BUILD_DIR)/build_himix100;\
	cmake -DCMAKE_TOOLCHAIN_FILE=$(CMAKE_DIR)/toolchain-himix100.cmake -DCMAKE_BUILD_TYPE=Release ../../..;\
	make -j8	

############################
# jz_t31                   #
############################
.PHONY : jz_t31
jz_t31:
	@echo "Build jz_t31"
	$(Q) mkdir -p $(BUILD_DIR)/build_jz_t31 2>/dev/null
	$(Q) rm -rf $(BUILD_DIR)/build_jz_t31/*
	$(Q) cd $(BUILD_DIR)/build_jz_t31;\
	cmake -DCMAKE_TOOLCHAIN_FILE=$(CMAKE_DIR)/toolchain-jz_t31.cmake -DCMAKE_BUILD_TYPE=Release ../../..;\
	make -j8	

############################
# stm32                    #
############################
.PHONY : stm32
stm32:
	@echo "Build stm32"
	$(Q) mkdir -p $(BUILD_DIR)/build_stm32 2>/dev/null
	$(Q) rm -rf $(BUILD_DIR)/build_stm32/*
	$(Q) cd $(BUILD_DIR)/build_stm32;\
	cmake -DCMAKE_TOOLCHAIN_FILE=$(CMAKE_DIR)/toolchain-stm32.cmake -DCMAKE_BUILD_TYPE=Release ../../..;\
	make -j8

############################
# esp32                    #
############################
.PHONY : esp32
esp32:
	@echo "Build esp32"
	$(Q) mkdir -p $(BUILD_DIR)/build_esp32 2>/dev/null
	$(Q) rm -rf $(BUILD_DIR)/build_esp32/*
	$(Q) cd $(BUILD_DIR)/build_esp32;\
	cmake -DCMAKE_TOOLCHAIN_FILE=$(CMAKE_DIR)/toolchain-esp32.cmake -DCMAKE_BUILD_TYPE=Release ../../..;\
	make -j8

############################
# rasp                     #
############################
.PHONY : rasp
rasp:
	@echo "Build rasp"
	$(Q) mkdir -p $(BUILD_DIR)/build_rasp 2>/dev/null
	$(Q) rm -rf $(BUILD_DIR)/build_rasp/*
	$(Q) cd $(BUILD_DIR)/build_rasp;\
	cmake -DCMAKE_TOOLCHAIN_FILE=$(CMAKE_DIR)/rasp.cmake -DCMAKE_BUILD_TYPE=Release ../../..;\
	make -j8	

######################################################################
# all                                                                #
######################################################################
.PHONY : all
all: codeformat lint x64 x86 himix100 jz_t31 stm32 esp32
	echo "build all"	
	
######################################################################
# Generate a list of changes since last commit to 'master' branch    #
######################################################################
.PHONY : CHANGELOG
CHANGELOG:
	git log master --format="*    %s" | sort | uniq > CHANGELOG-UNRELEASED